package com.zws.cucumber.util;

import com.zws.cucumber.util.colorfullog.ZwsColorfulLogger;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.SystemUtils;
import org.slf4j.Logger;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.function.Function;
import java.util.stream.Stream;

public class ZwsJavaHomeUtil {

    private static final Logger logger = ZwsColorfulLogger.of(ZwsJavaHomeUtil.class);

    private static final String[] WINDOWS_JDK8_PATTERNS = new String[]{
            "jdk1.8.0",
            "jdk-8.",
            "LibericaJDK-8",
            "jdk8u"
    };

    public static String findJdk8Home() {
        if (SystemUtils.IS_OS_WINDOWS) {
            logger.info("find openjdk8 in windows");
            return findWindowsJdk8Home();

        } else if (System.getenv().containsKey("WSL_DISTRO_NAME")) {
            logger.info("find openjdk8 in wsl");
            return findLinuxJdk8HomeFromJavaHome();

        } else if (SystemUtils.IS_OS_LINUX) {
            logger.info("find openjdk8 in linux(specified for jenkins)");
            return findJdk8HomeFromDirectory(new File("/"));

        } else {
            throw new RuntimeException("Unsupported OS");
        }
    }

    public static String findWindowsJdk8Home() {
        String jdk8Home = findWindowsJdk8HomeFromJavaHome();
        if (jdk8Home != null) {
            return jdk8Home;
        }
        return findWindowsJdk8HomeFromProgramFiles();
    }

    public static String findWindowsJdk8HomeFromProgramFiles() {
        final String PATH_PROGRAM_FILES = "C:\\Program Files";

        return Optional.ofNullable(findJdk8HomeFromDirectory(new File(PATH_PROGRAM_FILES + "\\Java"))) // C:\Program Files\Java
                .or(() -> Optional.ofNullable(findJdk8HomeFromDirectory(new File(PATH_PROGRAM_FILES + "\\Eclipse Adoptium")))) // C:\Program Files\Eclipse Adoptium
                .or(() -> Optional.ofNullable(findJdk8HomeFromDirectory(new File(PATH_PROGRAM_FILES + "\\BellSoft")))) // C:\Program Files\BellSoft
                .or(() -> Optional.ofNullable(findJdk8HomeFromDirectory(new File(PATH_PROGRAM_FILES)))) // C:\Program Files
                .orElse(null);
    }

    public static String findWindowsJdk8HomeFromJavaHome() {
        String javaHome = System.getenv("JAVA_HOME");
        if (javaHome == null || javaHome.trim().isEmpty()) {
            return null;
        }
        javaHome = javaHome.replace('/', '\\');
        if (javaHome.endsWith("\\")) {
            javaHome = javaHome.substring(0, javaHome.length() - 1);
        }
        if (!javaHome.contains("\\")) {
            return null;
        }

        File dir = new File(javaHome.substring(0, javaHome.lastIndexOf("\\") + 1));
        return findJdk8HomeFromDirectory(dir);
    }

    public static String findLinuxJdk8HomeFromJavaHome() {
        String javaHome = System.getenv("JAVA_HOME");
        logger.info("JAVA_HOME: {}", javaHome);
        if (javaHome == null || javaHome.trim().isEmpty()) {
            return null;
        }
//        javaHome = javaHome.replace('/', '\\');
        if (javaHome.endsWith("/")) {
            javaHome = javaHome.substring(0, javaHome.length() - 1);
        }
        logger.info("JAVA_HOME: {}", javaHome);
        if (!javaHome.contains("/")) {
            return null;
        }

        File dir = new File(javaHome.substring(0, javaHome.lastIndexOf("/") + 1));
        logger.info("JAVA_HOME: {}", dir.getAbsolutePath());
        return findJdk8HomeFromDirectory(dir);
    }

    public static String findJdk8HomeFromDirectory(File dir) {
        if (dir.exists() && dir.isDirectory()) {
            List<String> list = new ArrayList<>();
            for (File f : dir.listFiles()) {

                boolean isMatched = Stream.of(WINDOWS_JDK8_PATTERNS)
                        .anyMatch(pattern -> StringUtils.containsIgnoreCase(f.getName(), pattern));

                if (isMatched) {
                    list.add(f.getAbsolutePath());
                }
            }
            Function<String, Integer> indexOf = (String s) -> {
                for (int i = 0; i < WINDOWS_JDK8_PATTERNS.length; i++) {
                    if (StringUtils.containsIgnoreCase(s, WINDOWS_JDK8_PATTERNS[i])) {
                        return i;
                    }
                }
                return -1;
            };
            if (!list.isEmpty()) {
                list.sort((o1, o2) -> {
                    int i1 = indexOf.apply(o1);
                    int i2 = indexOf.apply(o2);
                    if (i1 == i2) {
                        return o2.compareTo(o1);
                    }
                    return Integer.compare(i1, i2);
                });
                logger.info("found jdk8 home: <y>[<bold>{}</bold>, {}]</y>",
                        list.get(0), String.join(", ", list.subList(1, list.size())));
                return list.get(0);
            }
        }
        return null;
    }

}
